package git.soulbgm.common.wrapper;

import git.soulbgm.config.KeyConfig;
import git.soulbgm.utils.AesUtil;
import org.apache.tomcat.util.http.fileupload.IOUtils;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
import java.util.HashMap;
import java.util.Map;

/**
 * 请求包装
 *
 * @author SoulBGM
 * @date 2023-10-17
 */
public class RequestWrapper extends HttpServletRequestWrapper {

    /**
     * 参数
     */
    private final Map<String, String[]> params;

    /**
     * Http请求对象
     */
    private final HttpServletRequest request;

    /**
     * 请求主体
     */
    private byte[] requestBody;

    public RequestWrapper(HttpServletRequest request) {
        super(request);
        this.request = request;
        KeyConfig config = KeyConfig.getConfig();
        String ck = request.getHeader(KeyConfig.HEADER_CK);
        String uniqueKey = config.getUniqueKey();
        Map<String, String[]> parameterMap = request.getParameterMap();
        this.params = new HashMap<>(parameterMap.size());
        if (uniqueKey.equals(ck) || !config.isDecrypt()) {
            this.params.putAll(parameterMap);
        } else if (config.isDecrypt()) {
            parameterMap.forEach((k, v) -> {
                String[] newValue = new String[v.length];
                for (int i = 0; i < v.length; i++) {
                    try {
                        newValue[i] = AesUtil.decrypt(v[i], uniqueKey);
                    } catch (Exception e) {
                        newValue[i] = v[i];
                    }
                }
                this.params.put(k, newValue);
            });
        }
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        if (null == this.requestBody) {
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            IOUtils.copy(request.getInputStream(), outputStream);
            this.requestBody = outputStream.toByteArray();
        }

        ByteArrayInputStream inputStream = new ByteArrayInputStream(requestBody);

        return new ServletInputStream() {

            @Override
            public boolean isFinished() {
                return false;
            }

            @Override
            public boolean isReady() {
                return false;
            }

            @Override
            public void setReadListener(ReadListener listener) {
                throw new UnsupportedOperationException();
            }

            @Override
            public int read() {
                return inputStream.read();
            }
        };
    }

    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(this.getInputStream()));
    }

    @Override
    public Map<String, String[]> getParameterMap() {
        return this.params;
    }

    @Override
    public String getParameter(String name) {
        String[] v = params.get(name);
        if (v == null || v.length == 0) {
            return null;
        }
        return v[0];
    }

    @Override
    public String[] getParameterValues(String name) {
        return params.get(name);
    }
}
